package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.zzyl.constant.CacheConstant;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * @Description ResourceServiceImpl
 * @Author chenchuang
 * @Date 2024-08-31
 */
@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    /**
     * @param resourceDto
     * @return List<ResourceVo>
     *  查询资源列表
     */
    @Cacheable(value = CacheConstant.RESOURCE_LIST ,key ="#resourceDto.hashCode()")
    @Override
    public List<ResourceVo> findResourceList(ResourceDto resourceDto) {
        List<Resource> resourceList=resourceMapper.selectList(resourceDto);
        return BeanUtil.copyToList(resourceList, ResourceVo.class);
    }

    /**
     * @param resourceDto
     * @return TreeVo
     *  资源树形
     */
    @Cacheable(value = CacheConstant.RESOURCE_TREE )
    @Override
    public TreeVo resourceTreeVo(ResourceDto resourceDto) {
        //1.构建查询条件
        ResourceDto dto = ResourceDto.builder().dataState(SuperConstant.DATA_STATE_0)
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .resourceType(SuperConstant.MENU)
                .build();
        //2.查询所有资源数据
        List<Resource> resourceList = resourceMapper.selectList(dto);
        if(EmptyUtil.isNullOrEmpty(resourceList)){
            throw new RuntimeException("资源列表错误");
        }
        //3.定义返回的树形集合
        List<TreeItemVo> treeVoList = new ArrayList<>();
        //4.使用hutool工具获取树形结构
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        //自定义名称由原有的name改成label
        treeNodeConfig.setNameKey("label");
        //利用hutool中的树形菜单功能实现
        List<Tree<String>> treeList = TreeUtil.build(resourceList,SuperConstant.ROOT_PARENT_ID,treeNodeConfig,
                (resource, treeNode) -> {
                    treeNode.setName(resource.getResourceName());
                    treeNode.setId(resource.getResourceNo());
                    treeNode.setParentId(resource.getParentResourceNo());
                });
        //5.集合泛型转换
        List<TreeItemVo> childTreeVoList = BeanUtil.copyToList(treeList, TreeItemVo.class);
        //6.由于没有根节点，构建跟节点信息
        TreeItemVo treeItemVo = TreeItemVo.builder().id(SuperConstant.ROOT_PARENT_ID).label("智慧养老院").children(childTreeVoList).build();
        //7.封装到树形集合中
        treeVoList.add(treeItemVo);
        //数据返回
        return new TreeVo(treeVoList);
    }

    /**
     * @param resourceDto
     * @return String
     *  创建资源编号
     */
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    @Override
    public void createResource(ResourceDto resourceDto) {
        //2.类型转换拷贝
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        //3.同步父资源状态和子资源状态一致
        Resource parentResourceNo = resourceMapper.selectByParentResourceNo(resource.getParentResourceNo());
        resource.setDataState(parentResourceNo.getDataState());
        //4.添加子资源编号
        String resourceNo = createResourceNo(resource);
        resource.setResourceNo(resourceNo);
        //1.调用新增mapper接口
        resourceMapper.insert(resource);
    }
    /**
     * @param menuId
     * @return void
     *  删除资源菜单
     */
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    @Override
    public void deleteByMenuId(String menuId) {
        ResourceDto parentDto = ResourceDto.builder().parentResourceNo(menuId).build();
        List<Resource> resourceList = resourceMapper.selectList(parentDto);
        if(EmptyUtil.isNullOrEmpty(resourceList)){
            resourceMapper.deleteByMenuId(menuId);
        }else {
            throw new RuntimeException("存在子菜单，不允许删除");
        }
    }
    /**
     * @param resourceDto
     * @return void
     *  修改资源信息
     */
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    @Transactional
    @Override
    public void update(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        //1.创造新的子资源编号
        String newResourceNO =createResourceNo(resource);
        //2.递归修改子菜单
        String resourceNo = resourceDto.getResourceNo();
        ResourceDto parentResourceDto = ResourceDto.builder().parentResourceNo(resourceNo).build();
        List<Resource> resourceList = resourceMapper.selectList(parentResourceDto);
        if(!EmptyUtil.isNullOrEmpty(resourceList)){
            List<ResourceDto> childrenResourceDtoList = BeanUtil.copyToList(resourceList, ResourceDto.class);
            childrenResourceDtoList.forEach(childrenResourceDto -> {
                childrenResourceDto.setParentResourceNo(newResourceNO);
                update(childrenResourceDto);
            });
        }
        //3.设置新的资源编号
        resource.setDataState(SuperConstant.DATA_STATE_0);
        resource.setResourceNo(newResourceNO);
        resourceMapper.updateByPrimaryKeySelective(resource);

    }

    /**
     * @param resourceDto
     * @return void
     *  修改资源状态
     */
    @Caching(evict = {@CacheEvict(value = CacheConstant.RESOURCE_LIST ,allEntries = true),
            @CacheEvict(value = CacheConstant.RESOURCE_TREE ,allEntries = true)})
    @Override
    public void updateState(ResourceDto resourceDto) {
        Resource resource = BeanUtil.copyProperties(resourceDto, Resource.class);
        String parentResourceNo = resourceDto.getParentResourceNo();
        Resource parentResource = resourceMapper.selectByParentResourceNo(parentResourceNo);
        if(Objects.equals(parentResource.getDataState(), SuperConstant.DATA_STATE_1)&& Objects.equals(resourceDto.getDataState(), SuperConstant.DATA_STATE_0)){
            throw new BaseException(BasicEnum.PARENT_DEPT_DISABLE);
        }
        resourceMapper.updateByResourceNoSelective(resource);
        String resourceNo = resourceDto.getResourceNo();
        ResourceDto resourceDto1 = ResourceDto.builder().parentResourceNo(resourceNo).build();
        List<Resource> resourceList = resourceMapper.selectList(resourceDto1);
        if(!EmptyUtil.isNullOrEmpty(resourceList)){
            List<ResourceDto> resourceDtos = BeanUtil.copyToList(resourceList, ResourceDto.class);
            resourceDtos.forEach(resource1 -> {
                resource1.setDataState(resource.getDataState());
                updateState(resource1);
            });
        }
    }

    @Override
    public List<MenuVo> menus(Long userId) {
        List<MenuVo> menuVoList = resourceMapper.findListByUserId(userId);

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("resourceNo");
        treeNodeConfig.setParentIdKey("parentResourceNo");
        List<Tree<String>> treeList = TreeUtil.build(menuVoList, SuperConstant.ROOT_PARENT_ID, treeNodeConfig,(treeNode,menuVo)->{
            menuVo.setName(treeNode.getName());
            menuVo.setId(treeNode.getResourceNo());
            menuVo.setParentId(treeNode.getParentResourceNo());
            menuVo.putExtra("path", treeNode.getPath());
            menuVo.putExtra("redirect","/"+treeNode.getName());
            menuVo.putExtra("meta", new MenuMetaVo(treeNode.getName(),"",null));
        });
        List<MenuVo> menuVoList1 = BeanUtil.copyToList(treeList, MenuVo.class);
        return menuVoList1;
    }

    /**
     * @param resource
     * @return String
     *  创建资源编号
     */
    private String createResourceNo(Resource resource) {
        //1、如果是菜单，以及父资源编号是否大于三级
        if(resource.getResourceType().equals("m")
                &&NoProcessing.processString(resource.getParentResourceNo()).length()/3>=5){
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }

        //2.不大于三级，查询父资源编号下是否包含子资源
        ResourceDto resourceDto = ResourceDto.builder().parentResourceNo(resource.getParentResourceNo()).build();
        List<Resource> resourceList = resourceMapper.selectList(resourceDto);

        if(EmptyUtil.isNullOrEmpty(resourceList)){
            return NoProcessing.createNo(resource.getParentResourceNo(),false);
        }
        else {
            Long l = resourceList.stream().map(resource1 -> Long.valueOf(resource1.getResourceNo())).max(Comparator.comparing(Long::intValue)).get();
            return NoProcessing.createNo(String.valueOf(l),true);
        }

    }
}
